﻿namespace ConsoleGame1
{
    using System;
    using System.IO;
    using System.Threading;

    public class Champion
    {
        private char letter;

        public Champion(char ch)
        {
            this.letter = ch;
        }

        public char Letter
        {
            get
            {
                return this.letter;
            }
        }
    }

    public class ConsoleGame1
    {
        // Global vars.
        static int playerX = 12;
        static int playerY = 0;
        static int platformHoleLenght = 10;
        static Random rdm = new Random();
        static ConsoleKeyInfo input;
        static int score = 0;
        static int bonusLives = 0;
        static int bonusCount = 0;
        static Champion champ;
        static bool getBackToMenu = false;

        // Balance variables
        static int addToScore = 0;
        static int balanceLives = 0;

        // Vars for first platform.
        static int firstPlatformX = 0;
        static int firstPlatformY = 29;
        static int moveUpFirstPlatform = 0;
        static int firstPlatformHoleX = rdm.Next(10, 26); // This number shows where the hole begins at the X + the lenght of the hole, wich is 10.

        // Vars for second platform.
        static int secondPlatformX = 0;
        static int secondPlatformY = 29;
        static int moveUpSecondPlatform = 15;
        static int secondPlatformHoleX = rdm.Next(10, 26);

        static void DisableCursorGetRidOfScrollBarsAndSetWindowSize()
        {
            // Disable cursor.
            Console.CursorVisible = false;
            Console.SetWindowSize(25, 30);

            // DisableScrollBars.
            Console.BufferWidth = Console.WindowWidth;
            Console.BufferHeight = Console.WindowHeight;
        }

        static void HighScoreWrite()
        {
            try
            {
                StreamReader highScoreRead = new StreamReader("highscorefile.txt");
                string currentHighScore = highScoreRead.ReadLine();
                int currentHighScoreInt = int.Parse(currentHighScore);
                highScoreRead.Close();

                if (currentHighScoreInt < score)
                {
                    StreamWriter highScoreWrite = new StreamWriter("highscorefile.txt");
                    
                    using (highScoreWrite)
                    {
                        highScoreWrite.WriteLine(score);
                    }
                }
                HighScoreWriteOnScreen();
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (IOException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (FormatException)
            {
                Console.WriteLine();
                Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                Console.WriteLine();
            }
        }

        private static void AddBonusLives()
        {
            // Give lifes at different intervals for differnt lvls.
            if (bonusCount % balanceLives == 0 && moveUpFirstPlatform == 29)
            {
                bonusLives++;
            }
        }

        static void CheckInFirstPlatform(int escPressed)
        {
            if (bonusLives == 0)
            {
                // Resize window for Menu sign
                Console.ForegroundColor = ConsoleColor.White;
                Console.Clear();
                Console.Beep();
                Console.SetWindowSize(60, 25);
                PrintGameOverSign();

                Console.WriteLine();
                Console.WriteLine("Game Over Press Esc");
                Console.WriteLine("to go back to main menu.");
                Console.Write("Your score is : ");
                Console.WriteLine(score);

                // Save the high score in the highscorefile.txt
                HighScoreWrite();
                while (true)
                {
                    escPressed = CheckForPressedEsc(escPressed);
                    if (escPressed == 1)
                    {
                        getBackToMenu = true;
                        return;
                    }
                }
            }
            else
            {
                bonusLives--;
            }
        }

        static void CheckInSecondPlatform(int escPressed)
        {
            if (bonusLives == 0)
            {
                // Resize window for Menu sign
                Console.Clear();
                Console.Beep();
                Console.SetWindowSize(60, 25);
                PrintGameOverSign();

                Console.WriteLine();
                Console.WriteLine("Game Over Press Esc");
                Console.WriteLine("to go back to main menu.");
                Console.Write("Your score is : ");
                Console.WriteLine(score);

                // Save the high score in the highscorefile.txt
                HighScoreWrite();

                while (true)
                {
                    escPressed = CheckForPressedEsc(escPressed);
                    if (escPressed == 1)
                    {
                        getBackToMenu = true;
                        return;
                    }
                }
            }
            else
            {
                bonusLives--;
            }
        }

        static void CollisionDetect()
        {
            int escPressed = 0;

            // Find second platforms hole!
            if (!(moveUpSecondPlatform < 29) && !(playerX > Console.WindowWidth - secondPlatformHoleX && playerX < Console.WindowWidth - secondPlatformHoleX + 10))
            {
                CheckInFirstPlatform(escPressed);
            }

            // Find first platforms hole!
            if (!(moveUpFirstPlatform < 29) && !(playerX > Console.WindowWidth - firstPlatformHoleX && playerX < Console.WindowWidth - firstPlatformHoleX + 10))
            {
                CheckInSecondPlatform(escPressed);
            }
        }

        private static void DeleteHighScore()
        {
            try
            {
                // Write a 0 in the highscorefile.txt
                using (StreamWriter write = new StreamWriter("highscorefile.txt"))
                {
                    write.WriteLine("0");
                }
            }
            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (IOException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
            }
            catch (FormatException)
            {
                Console.WriteLine();
                Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                Console.WriteLine();
            }
        }

        private static void HighScoreWriteOnScreen()
        {
            try
            {
                using (StreamReader read = new StreamReader("highscorefile.txt"))
                {
                    Console.WriteLine("Your High Score is {0} ", read.ReadLine());
                }
            }

            catch (FileNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (IOException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (UnauthorizedAccessException e)
            {
                Console.WriteLine(e.Message);
            }

            catch (FormatException)
            {
                Console.WriteLine();
                Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                Console.WriteLine();
            }
        }

        private static void PrintGameOverSign()
        {
            string[,] g = new string[,]
         {
             { "#", "#", "#", "#", "#" },
             { "#", " ", " ", " ", " " },
             { "#", " ", "#", "#", "#" },
             { "#", " ", " ", " ", "#" },
             { "#", "#", "#", "#", "#" },
         };

            string[,] a = new string[,]
         {
             { " ", " ", "#", " ", " " },
             { " ", "#", " ", "#", " " },
             { "#", " ", " ", " ", "#" },
             { "#", "#", "#", "#", "#" },
             { "#", " ", " ", " ", "#" },
         };

            string[,] m = new string[,]
         {
            { " ", "#", " ", "#", " " },
            { "#", "#", "#", "#", "#" },
            { "#", " ", "#", " ", "#" },
            { "#", " ", "#", " ", "#" },
            { "#", " ", " ", " ", "#" },
         };

            string[,] e = new string[,]
         {
            { "#", "#", "#", "#", "#" },
            { "#", " ", " ", " ", " " },
            { "#", "#", "#", "#", " " },
            { "#", " ", " ", " ", " " },
            { "#", "#", "#", "#", "#" },
         };

            string[,] o = new string[,]
         {
            { "#", "#", "#", "#", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", "#", "#", "#", "#" },
         };

            string[,] v = new string[,]
         {
            { "#", " ", " ", " ", "#" },
            { "#", "#", " ", "#", "#" },
            { "#", "#", " ", "#", "#" },
            { " ", "#", "#", "#", " " },
            { " ", " ", "#", " ", " " },
         };

            string[,] r = new string[,]
          {
            { "#", "#", "#", "#", "#" },
            { "#", " ", " ", " ", "#" },
            { "#", "#", "#", "#", "#" },
            { "#", " ", "#", " ", " " },
            { "#", " ", " ", "#", "#" },
         };
            PrintArray(g, 0, 0);
            PrintArray(a, 8, 0);
            PrintArray(m, 16, 0);
            PrintArray(e, 24, 0);
            Console.WriteLine();
            PrintArray(o, 0, 7);
            PrintArray(v, 8, 7);
            PrintArray(e, 16, 7);
            PrintArray(r, 24, 7);
        }

        static void PrintArray(string[,] array, int cursurPositionAtCow, int curstorPositionAtRow)
        {
            for (int row = 0; row < array.GetLength(0); row++)
            {
                for (int col = 0; col < array.GetLength(1); col++)
                {
                    Console.SetCursorPosition(cursurPositionAtCow + col, curstorPositionAtRow + row);
                    Console.Write("{0} ", array[row, col]);
                }
                Console.WriteLine();
            }
        }

        private static int CheckForPressedEsc(int isEscPressed)
        {
            if (Console.KeyAvailable)
            {
                ConsoleKeyInfo esc = Console.ReadKey();

                if (esc.Key == ConsoleKey.Escape)
                {
                    return isEscPressed = 1;
                }
            }
            return isEscPressed = 0;
        }

        private static int ChooseLevel()
        {
            Console.WriteLine("Choose level: ");
            Console.WriteLine("1. Easy");
            Console.WriteLine("2. Normal");
            Console.WriteLine("3. Hard");
            return int.Parse(Console.ReadLine());
        }

        private static char ChooseChampion()
        {
            Console.WriteLine("Choose champion: ");
            Console.WriteLine("1. @");
            Console.WriteLine("2. #");
            Console.WriteLine("3. $");
            string champ = Console.ReadLine();
            switch (champ)
            {
                case "1":
                    champ = "@";
                    break;
                case "2":
                    champ = "#";
                    break;
                case "3":
                    champ = "$";
                    break;
            }
            return char.Parse(champ);
        }

        static void Main()
        {
            Console.WriteLine("Game menu");
            while (true)
            {
                Console.WriteLine("Press 1 to play.");
                Console.WriteLine("Press 2 to view highscore.");
                Console.WriteLine("Press 3 to delete highscore.");
                int choice = int.Parse(Console.ReadLine());

                // This fixes the platforms starting point before a new game begins.
                moveUpFirstPlatform = 0;
                moveUpSecondPlatform = 15;
                // Set All scores to 0.
                score = 0;
                bonusLives = 0;
                bonusCount = 0;

                // Menu options
                if (choice == 1)
                {
                    Console.Clear();
                    int level = ChooseLevel();
                    int sleep = 0;
                    if (level == 1)
                    {
                        sleep = 50;
                        addToScore = 1;
                        balanceLives = 6;
                    }
                    else if (level == 2)
                    {
                        sleep = 10;
                        addToScore = 2;
                        balanceLives = 8;
                    }
                    else
                    {
                        sleep = -65;
                        addToScore = 4;
                        balanceLives = 16;
                    }

                    char letter = ChooseChampion();
                    champ = new Champion(letter);

                    Thread.Sleep(500);
                    Console.WriteLine("Get Ready!!");

                    while (true)
                    {
                        DisableCursorGetRidOfScrollBarsAndSetWindowSize();
                        Draw();
                        AddBonusLives();
                        MoveLogic();
                        CollisionDetect();

                        // Get Back to menu
                        if (getBackToMenu == true)
                        {
                            getBackToMenu = false;
                            Console.Clear();
                            break;
                        }

                        bonusCount++;
                        Console.SetCursorPosition(0, 29);
                        Console.Write("Score : {0}  lives: {1}", score, bonusLives);
                        Thread.Sleep(120 + sleep);
                        Console.Clear();
                    }
                }
                else if (choice == 2)
                {
                    try
                    {
                        using (StreamReader highScoreRead = new StreamReader("highscorefile.txt"))
                        {
                            Console.WriteLine();
                            Console.Write("Highscore is :");
                            Console.WriteLine(highScoreRead.ReadLine());
                            Console.WriteLine();
                        }
                    }
                    catch (FileNotFoundException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (DirectoryNotFoundException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (IOException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (UnauthorizedAccessException e)
                    {
                        Console.WriteLine(e.Message);
                    }

                    catch (FormatException)
                    {
                        Console.WriteLine();
                        Console.WriteLine("The Highscorefile.txt might be empty or the input is not i a correct format!");
                        Console.WriteLine();
                    }
                }
                else if (choice == 3)
                {
                    DeleteHighScore();
                    Console.WriteLine();
                    Console.WriteLine("Highscore deleted!");
                }
                else
                {
                    Console.WriteLine("Sorry wrong command!");
                }
            }
        }

        private static void MoveLogic()
        {
            if (Console.KeyAvailable)
            {
                input = Console.ReadKey();
                while (Console.KeyAvailable)
                {
                    Console.ReadKey(true);
                }

                if (input.Key == ConsoleKey.RightArrow)
                {
                    CheckOutOfBound();
                    playerX++;
                }
                if (input.Key == ConsoleKey.LeftArrow)
                {
                    CheckOutOfBound();
                    playerX--;
                }
            }
        }

        private static void Draw()
        {
            // Console.ForegroundColor = ConsoleColor.White;
            DrawPlayer();
            DrawPlatform();
            DrawPlatformTwo();
        }

        private static void DrawPlatform()
        {
            // Restart once we hit the top.
            if (moveUpFirstPlatform == 29)
            {
                moveUpFirstPlatform = 0;
                // Generate new rdm number after every refresh to change the hole position.
                firstPlatformHoleX = rdm.Next(10, 26);
                score += addToScore;
            }

            Console.SetCursorPosition(firstPlatformX, firstPlatformY - moveUpFirstPlatform);
            // Draw one line.
            if (score % (balanceLives * 2) == 0)
            {
                ChangeTextColor();
            }
            Console.Write(new string('_', Console.WindowWidth - firstPlatformHoleX));
            Console.Write(new string(' ', platformHoleLenght));
            Console.Write(new string('_', firstPlatformHoleX - platformHoleLenght));
            moveUpFirstPlatform++;
        }

        private static void DrawPlatformTwo()
        {
            // Restart once we hit the top.
            if (moveUpSecondPlatform == 29)
            {
                moveUpSecondPlatform = 0;
                // Generate new rdm number after every refresh to change the hole position.
                secondPlatformHoleX = rdm.Next(10, 26);
                score += addToScore;
            }

            Console.SetCursorPosition(secondPlatformX, secondPlatformY - moveUpSecondPlatform);
            // Draw one line.
            if (score % (balanceLives * 2) == 0)
            {
                ChangeTextColor();
            }
            Console.Write(new string('_', Console.WindowWidth - secondPlatformHoleX));
            Console.Write(new string(' ', platformHoleLenght));
            Console.Write(new string('_', secondPlatformHoleX - platformHoleLenght));
            moveUpSecondPlatform++;

        }

        private static void ChangeTextColor()
        {
            Random rnd = new Random();
            int randomColor = rdm.Next(1, 8);
            switch (randomColor)
            {
                case 1:
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
                case 2:
                    Console.ForegroundColor = ConsoleColor.DarkYellow;
                    break;
                case 3:
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    break;
                case 4:
                    Console.ForegroundColor = ConsoleColor.Gray;
                    break;
                case 5:
                    Console.ForegroundColor = ConsoleColor.Green;
                    break;
                case 6:
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    break;
                case 7:
                    Console.ForegroundColor = ConsoleColor.Red;
                    break;
                case 8:
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    break;
                default: throw new IndexOutOfRangeException();
            }
        }

        private static void CheckOutOfBound()
        {
            if (playerX == 0)
            {
                playerX++;
            }
            else if (playerX == Console.WindowWidth - 1)
            {
                playerX--;
            }
        }

        private static void DrawPlayer()
        {
            Console.SetCursorPosition(playerX, playerY);
            Console.Write(champ.Letter);
        }

    }
}